package Controller;

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.image.BufferedImage;

import root.MapObjects;
import View.*;
import Model.Construction.Infrastructure;

/** La class EcouteurDeBoard se charge d'ecouter les evenements
 * (mouvement de souris et clic) sur le terrain de la ville
 * pour appliquer les selection faites dans barre de selection
 * @author MAADJO
 */

public class EcouteurDeBoard extends MouseAdapter implements MouseMotionListener, ActionListener {

	BoardPanel boardpanel;
	LeftPanel leftpanel;
	int xSrc, ySrc, xDest, yDest;
	Curseur curseur;
	boolean selection;


	public EcouteurDeBoard(BoardPanel bp, Curseur c) {
		leftpanel =  ((Fenetre) bp.getTopLevelAncestor()).getLeftPanel();
		boardpanel = bp;
		bp.setListener(this);
		curseur = c;
		selection = false; // par defaut pas de selection
	}

	public void mousePressed(MouseEvent e) {
		if(e.getButton() == MouseEvent.BUTTON3) {
			//si clic droit info le sur batiment.
			leftpanel.getCurseurPanel().update(XyToColLigne(e.getX(),e.getY()));
		} else {
			xSrc = e.getX();
			ySrc = e.getY();

			boolean multiple = MapObjects.isMultiple(curseur.getInfra());
			if(multiple) {
				boardpanel.bufferiserPlateau();
				selection = true;
				boardpanel.setSelection(selection);
			} else {
				Point p = XyToColLigne(xSrc,ySrc);
				if(curseur.getInfra().equals(".Destruction")) {
					curseur.destruction(p.x, p.y);
				} else {
					curseur.construction(p.x, p.y);
				}
				boardpanel.repaint();
			}
		}
	}


	public void mouseDragged(MouseEvent e) {
		xDest = e.getX();
		yDest = e.getY();

		//cas limite, on elimine les points hors du panel
		if(xDest > boardpanel.getWidth()-1)
			xDest = boardpanel.getWidth()-1;
		else if (xDest < 0)
			xDest = 0;

		if(yDest > boardpanel.getHeight()-1)
			yDest = boardpanel.getHeight()-1;
		else if (yDest < 0)
			yDest = 0;

		Point p = XyToColLigne(xDest,yDest);
		int ligne = p.y;
		int colonne = p.x;
		Infrastructure inf = curseur.getBoard().getObject(colonne, ligne);

		if (selection) {
			// calcule de la surface recouverte
			if(calculerZone()) {
				boardpanel.setConstructible(true);
			} else {
				boardpanel.setConstructible(false);
			}
			boardpanel.repaint();
		} else if ((!selection) && inf == null){
			//on construit le non-multiple si la case est vide
			if(! curseur.getInfra().equals(".Destruction")) {
				curseur.construction(p.x, p.y);
				boardpanel.repaint();
			}
		}
	}


	public void mouseReleased(MouseEvent e) {
		if(selection) {
			selection = false;
			boardpanel.setSelection(false);
			boardpanel.setConstructible(true);
			xDest = e.getX();
			yDest = e.getY();


			//limite si le curseur est en dehors du board
			if(xDest > boardpanel.getWidth()-1)
				xDest = boardpanel.getWidth()-1;
			else if (xDest < 0)
				xDest = 0;

			if(yDest > boardpanel.getHeight()-1)
				yDest = boardpanel.getHeight()-1;
			else if (yDest < 0)
				yDest = 0;

			if(calculerZone()) {
				curseur.construction(boardpanel.SupGauche, boardpanel.InfDroite);
			}
			boardpanel.repaint();
			Fenetre f = (Fenetre) boardpanel.getTopLevelAncestor();
			f.getLeftPanel().repaint();
		}
	}


	public void mouseMoved(MouseEvent e) {}

	public void actionPerformed(ActionEvent e) {}// inutilisé

	public Point XyToColLigne(int x, int y) { // retourne col,ligne
		return new Point(x * boardpanel.getTailleTerrain() / boardpanel.getWidth(),
		                 y * boardpanel.getTailleTerrain() / boardpanel.getHeight());
	}

	public boolean  calculerZone() {
		//va renvoyer true si la zone recouverte est constructible
		//sinon renvoi false
		//Met a jours les variables d'affichage de la selection sur le boardpanel


		int xTop; // x le plus à gauche (le plus faible)
		int yTop; // y le plus haut (le plus faible)
		int xBottom; // x le plus à droite (le plus grand)
		int yBottom; // y le plus bas (le plus grand)

		xTop = xSrc < xDest ? xSrc : xDest;
		yTop = ySrc < yDest ? ySrc : yDest;
		xBottom = xSrc >= xDest ? xSrc : xDest;
		yBottom = ySrc >= yDest ? ySrc : yDest;



		Point top = XyToColLigne(xTop, yTop);
		Point bottom = XyToColLigne(xBottom, yBottom);


		int tmpcol = bottom.x;
		int tmpligne = bottom.y;
		int col = (bottom.x-top.x+1)%curseur.dummy.getLargeur();
		bottom.x += (curseur.dummy.getLargeur()-col)%curseur.dummy.getLargeur();
		int ligne = (bottom.y-top.y+1)%curseur.dummy.getHauteur();
		bottom.y += (curseur.dummy.getHauteur()-ligne)%curseur.dummy.getHauteur();

		if(bottom.x > curseur.getBoard().getTaille()) {
			bottom.x -= curseur.dummy.getLargeur();
		}
		if(bottom.y > curseur.getBoard().getTaille()) {
			bottom.y -= curseur.dummy.getHauteur();
		}

		int nbCons = ((bottom.x-top.x+1)/curseur.dummy.getLargeur()) *
			((bottom.y-top.y+1)/curseur.dummy.getHauteur());

		boardpanel.SupGauche = top;
		boardpanel.InfDroite = bottom;

		for(int x=top.x; x<=bottom.x;x++) {
			for(int y=top.y; y<=bottom.y;y++) {
				if(curseur.getBoard().getObject(y,x) != null)  {
					return false;
				}
			}
		}
		return (true && curseur.getVille().argentEstSuffisant(nbCons*curseur.dummy.getPrixConstruction()));
	}
}
